﻿using Dapper;
using System.Data;
using System.Diagnostics;
using System.Reflection;

namespace RockBus.Utilities
{
    public static class DapperExtensions
    {
        /// <summary>
        ///     Executes a normal query and returns the id which Oracle provided with the before insert trigger.
        /// </summary>
        /// <typeparam name="T">Type to return</typeparam>
        /// <param name="dbConn"></param>
        /// <param name="sql">Query to execute.</param>
        /// <param name="param">Object with properties to replace the placeholders.</param>
        /// <param name="fieldNameReturning">Name of the field to return the value from.</param>
        /// <param name="transaction">Transaction-variablet to use.</param>
        /// <param name="commandTimeout">Amount of time after which it stops.</param>
        /// <param name="commandType">Type of command to execute.</param>
        /// <returns></returns>
        public static T QueryReturning<T>(this IDbConnection dbConn, string sql, object param,
            string fieldNameReturning, IDbTransaction transaction = null, int? commandTimeout = null,
            CommandType? commandType = null)
        {
            sql = sql.Replace('@', ':');

            DynamicParameters dynParams = new DynamicParameters();
            foreach(var paramProperty in param.GetType().GetProperties(BindingFlags.Instance | BindingFlags.Public))
                dynParams.Add(paramProperty.Name, paramProperty.GetValue(param),
                    direction: ParameterDirection.Input);

            dynParams.Add(fieldNameReturning, dbType: DbType.Int64, direction: ParameterDirection.Output);
            Debug.WriteLine("{0}: {1}", "QueryReturning", new StackTrace().GetFrame(1).GetMethod().Name);
            dbConn.Execute(sql, dynParams, transaction, commandTimeout, commandType);
            // ????????????
            return dynParams.Get<T>(fieldNameReturning);
        }

        /// <summary>
        ///     Replaces all that at's with double colon's for Oracle to process the query correctly.
        /// </summary>
        /// <param name="dbConn"></param>
        /// <param name="sql">Query to execute.</param>
        /// <param name="param">Object with properties to replace the placeholders.</param>
        /// <param name="transaction">Transaction-variablet to use.</param>
        /// <param name="commandTimeout">Amount of time after which it stops.</param>
        /// <param name="commandType">Type of command to execute.</param>
        /// <returns>The normal Dapper Execute-method.</returns>
        public static int ExecuteOracleSafe(this IDbConnection dbConn, string sql, object param = null,
            IDbTransaction transaction = null, int? commandTimeout = null, CommandType? commandType = null)
        {
            sql = sql.Replace('@', ':');
            Debug.WriteLine("{0}: {1}", "ExecuteOracleSafe", new StackTrace().GetFrame(1).GetMethod().Name);
            return dbConn.Execute(sql, param, transaction, commandTimeout, commandType);
            /*
            int rowsAffected = dbConn.Execute(sql, (object) param); //, transaction, commandTimeout, commandType);

            return rowsAffected > 0 ? rowsAffected : 0;
            */
        }
    }
}